#ifndef __Point3_hpp__
#define __Point3_hpp__

#include "Point2.hpp"

namespace ge {

//----------------------------------------------------------------------------//
// Point3< T >
//----------------------------------------------------------------------------//

GE_PACK template < class T >
class GE_PACKED Point3
{
 public:

     Point3( void ) : x( (T)0 ), y( (T)0 ), z( (T)0 )
     {
     }

     Point3( const T& _xyz ) : x( _xy ), y( _xy ), z( _xyz )
     {
     }

     Point3( const T& _x, const T& _y, const T& _z = 0 ) : x( _x ), y( _y ), z( _z )
     {
     }

     Point3( const T _v[3] ) : x( _v[0] ), y( _v[1] ), z( _v[2] )
     {
     }

     Point3( const Point2< T >& _p, const T& _z = 0 ) : x( _p.x ), y( _p.y ), z( _z )
     {
     }

     Point3( const Point3& _p ) : x( _p.x ), y( _p.y ), z( _p.z )
     {
     }

     Point3& operator = ( const Point2< T >& _p )
     {
          return Set( _p );    
     }

     Point3& operator = ( const Point3& _p )
     {
          return Set( _p );    
     }

     Point3& operator = ( const T& _xyz )
     {
          return Set( _xyz );    
     }

     operator Point2< T > ( void ) const
     {
          return Point2< T >( x, y );
     }

     Point3& Set( const T& _xyz )
     {
          x = _xyz;
          y = _xyz;
          z = _xyz;
          return *this;
     }

     Point3& Set( const T& _x, const T& _y, const T& _z = 0 )
     {
          x = _x;
          y = _y;
          z = _z;
          return *this;
     }

     Point3& Set( const Point2< T >& _p, const T& _z = 0 )
     {
          x = _p.x;
          y = _p.y;
          z = _z;
          return *this;
     }

     Point3& Set( const Point3& _p )
     {
          x = _p.x;
          y = _p.y;
          z = _p.z;
          return *this;
     }

     Point3& FromPtr( const T _v[3] )
     {
          x = _v[0];
          y = _v[1];
          z = _v[2];
          return *this;
     }

     Point3& SetZero( void )
     {
          x = (T)0;
          y = (T)0;
          z = (T)0;
          return *this;
     }

     Point3& SetIdentity( void )
     {
          x = (T)1;
          y = (T)1;
          z = (T)1;
          return *this;
     }

     bool operator == ( const Point3& _p ) const
     {
          return x == _p.x && y == _p.y && z == _p.z;
     }

     bool operator < ( const Point3& _p ) const
     {
          return x < _p.x && y < _p.y && z < _p.z;
     }

     bool operator <= ( const Point3& _p ) const
     {
          return x <= _p.x && y <= _p.y && z <= _p.z;
     }

     bool operator != ( const Point3& _p ) const
     {
          return !(*this == _p);
     }

     bool operator > ( const Point3& _p ) const
     {
          return !(*this <= _p);
     }

     bool operator >= ( const Point3& _p ) const
     {
          return !(*this < _p);
     }

     Point3 operator + ( const Point3& _pt ) const
     {
          return Point3( x + _pt.x, y + _pt.y, z + _pt.z );
     }

     Point3 operator - ( const Point3& _pt ) const
     {
          return Point3( x - _pt.x, y - _pt.y, z - _pt.z );
     }

 public:

     static const Point3 Zero;
     static const Point3 Identity;

 public:

     union
     {
          struct { T x,y,z; };
          struct { T w,h,d; };
          struct { T width, height, depth; };
          T v[3];
     };

} GE_UNPACK;

template < class T > const Point3< T > Point3< T >::Zero( 0, 0, 0 );
template < class T > const Point3< T > Point3< T >::Identity( 1, 1, 1 );

typedef Point3< int > Point3i, Size3i;
typedef Point3< uint > Point3ui, Size3ui;
typedef Point3< float > Point3f, Size3f;

} // namespace ge

#endif//__Point3_hpp__
